package com.kinghood.productcenter.service.product.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.kinghood.infrastructure.model.KingHoodExceptionUtil;
import com.kinghood.infrastructure.model.constant.CommonConstants;
import com.kinghood.infrastructure.util.base.IdGenUtil;
import com.kinghood.infrastructure.util.UserUtil;
import com.kinghood.productcenter.common.model.constants.ProductConstant;
import com.kinghood.productcenter.common.model.dao.base.BaseAttributeValueDO;
import com.kinghood.productcenter.common.model.dao.product.ProductAttributeDO;
import com.kinghood.productcenter.common.model.dao.product.ProductSkuExtrasBaseDO;
import com.kinghood.productcenter.common.model.dao.product.ProductSkuSupplierBaseDO;
import com.kinghood.productcenter.common.model.dto.product.AttributeByProductIdDTO;
import com.kinghood.productcenter.common.model.enums.base.AttributeValueCodeEnum;
import com.kinghood.productcenter.common.model.vo.base.BaseAttributeVO;
import com.kinghood.productcenter.common.model.vo.product.ProductAttributeListVO;
import com.kinghood.productcenter.dao.base.BaseAttributeValueMapper;
import com.kinghood.productcenter.dao.product.ProductAttributeMapper;
import com.kinghood.productcenter.dao.product.ProductSkuExtrasBaseMapper;
import com.kinghood.productcenter.dao.product.ProductSkuSupplierBaseMapper;
import com.kinghood.productcenter.service.product.IProductAttributeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kinghood.productcenter.service.product.handler.ProductBaseHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author KingHood
 * @since 2023-12-20
 */
@RequiredArgsConstructor
@Slf4j
@Service
public class ProductAttributeServiceImpl extends ServiceImpl<ProductAttributeMapper, ProductAttributeDO> implements IProductAttributeService {

    @Resource
    private BaseAttributeValueMapper attributeValueMapper;
    private final ProductSkuExtrasBaseMapper productSkuExtrasBaseMapper;
    private final ProductSkuSupplierBaseMapper productSkuSupplierBaseMapper;

    /**
     * 通过code和商品id获取属性map
     *
     * @param showAttributeList 显示属性列表
     * @param productList       产品列表
     * @return 商品id, 属性列表
     * @author jp
     * @date 2023/12/26
     */
    @Override
    public Map<Long, List<ProductAttributeListVO>> getProductAttributeByCode(List<String> showAttributeList, List<Long> productList) {
        List<ProductAttributeListVO> result = this.baseMapper.getAllAttributeByCode(showAttributeList, productList);
        return attributeProcess(result);
    }

    /**
     * 通过code获取sku属性
     *
     * @param showAttributeList 显示属性列表
     * @param skuList           SKU列表
     * @return @return {@link Map }<{@link Long }, {@link List }<{@link ProductAttributeListVO }>>
     * @author jp
     * @date 2024/01/23 15:08
     */
    @Override
    public Map<Long, List<ProductAttributeListVO>> getSkuAttributeByCode(List<String> showAttributeList, List<Long> skuList) {
        List<ProductAttributeListVO> result = this.baseMapper.getSkuAttributeByCode(showAttributeList, skuList);
        return attributeProcess(result);
    }

    /**
     * 根据id把属性放入map
     *
     * @param result 后果
     * @return @return {@link Map }<{@link Long }, {@link List }<{@link ProductAttributeListVO }>>
     * @author jp
     * @date 2024/01/23 15:08
     */
    private Map<Long, List<ProductAttributeListVO>> attributeProcess(List<ProductAttributeListVO> result) {
        List<Long> attributeValueIdList = new ArrayList<>();
        for (ProductAttributeListVO attributeListVO : result) {
            if (AttributeValueCodeEnum.isMulti(attributeListVO.getAttributeValueCode()) && !StringUtils.isEmpty(attributeListVO.getValue())
                    && !"null".equals(attributeListVO.getValue())) {
                if (AttributeValueCodeEnum.CHECK_BOX.getCode().equals(attributeListVO.getAttributeValueCode())
                        || AttributeValueCodeEnum.SELECT.getCode().equals(attributeListVO.getAttributeValueCode())
                        || AttributeValueCodeEnum.LEVEL_SELECT.getCode().equals(attributeListVO.getAttributeValueCode())) {
                    String values = attributeListVO.getValue();
                    attributeValueIdList.addAll(Arrays.stream(values.split(","))
                            .map(Long::valueOf)
                            .collect(Collectors.toList()));
                } else {
                    attributeValueIdList.add(Long.valueOf(attributeListVO.getValue()));
                }
            }
        }
        // 修改下拉类的值，把id改为具体的值
        if (!CollectionUtils.isEmpty(attributeValueIdList)) {
            attributeValueIdList = attributeValueIdList.stream().distinct().collect(Collectors.toList());
            List<BaseAttributeValueDO> valueDTOList = attributeValueMapper.getValuesByList(attributeValueIdList);
            Map<Long, String> valueMap = valueDTOList.stream().collect(Collectors.toMap(BaseAttributeValueDO::getId,
                    BaseAttributeValueDO::getValue, (x, y) -> x));
            for (ProductAttributeListVO attributeListVO : result) {
                if (AttributeValueCodeEnum.isMulti(attributeListVO.getAttributeValueCode()) && !StringUtils.isEmpty(attributeListVO.getValue())
                        && !"null".equals(attributeListVO.getValue())) {
                    if (("CHECK_BOX").equals(attributeListVO.getAttributeValueCode()) || ("SELECT").equals(attributeListVO.getAttributeValueCode())
                            || ("LEVEL_SELECT").equals(attributeListVO.getAttributeValueCode())) {
                        String[] values = attributeListVO.getValue().split(",");
                        String transValue = Arrays.stream(values)
                                .map(Long::valueOf)
                                .map(valueMap::get)
                                .filter(StringUtils::isNotEmpty)
                                .collect(Collectors.joining(","));
                        attributeListVO.setValue(transValue);
                    } else {
                        attributeListVO.setValue(valueMap.get(Long.valueOf(attributeListVO.getValue())));
                    }
                }
            }
        }
        return result.stream()
                .collect(Collectors.groupingBy(ProductAttributeListVO::getId));
    }

    @Override
    public void deleteByProductId(Long id, List<Long> templateAttributeIdList, List<Integer> skuTypeList, List<Long> otherIdList) {

        if (CollectionUtils.isEmpty(templateAttributeIdList)) {
            return;
        }

        new LambdaUpdateChainWrapper<>(this.getBaseMapper())
                .eq(ProductAttributeDO::getProductId, id)
                .in(ProductAttributeDO::getAttributeId, templateAttributeIdList)
                .in(!CollectionUtils.isEmpty(skuTypeList),ProductAttributeDO::getBusinessType, skuTypeList)
                .in(!CollectionUtils.isEmpty(otherIdList),ProductAttributeDO::getBusinessId, otherIdList)
                .eq(ProductAttributeDO::getIsDelete, CommonConstants.IS_DELETE_N)
                .remove();

    }

    @Override
    public void saveList(Map<String, Object> attributes, Long productId, Long businessId, int businessType,
                         Map<String, BaseAttributeVO> attributeMap) {

        List<ProductAttributeDO> attributeList = new ArrayList<>();
        attributes.forEach((k, y) -> {
            if (ProductConstant.NO_ATTRIBUTE_LIST.contains(k)) {
                return;
            }
            BaseAttributeVO baseAttributeVO = attributeMap.get(k);
            KingHoodExceptionUtil.isNull(baseAttributeVO, "属性" + k + "不存在");

            ProductAttributeDO productAttributeDO = new ProductAttributeDO();
            productAttributeDO.setId(IdGenUtil.getId());
            productAttributeDO.setProductId(productId);
            productAttributeDO.setBusinessId(businessId);
            productAttributeDO.setBusinessType(businessType);
            productAttributeDO.setAttributeId(baseAttributeVO.getId());
            productAttributeDO.setAttributeCode(baseAttributeVO.getAttributeCode());
            productAttributeDO.setValue(ProductBaseHandler.handleAttributeValue(y));
            productAttributeDO.setValueFind(ProductBaseHandler.handleAttributeValueFind(productAttributeDO.getValue()));
            productAttributeDO.setValueType(baseAttributeVO.getValueType());
            productAttributeDO.setCreateTime(LocalDateTime.now());
            productAttributeDO.setUpdateTime(LocalDateTime.now());
            productAttributeDO.setCreateUserId(UserUtil.getUserId());
            attributeList.add(productAttributeDO);
        });
        this.saveBatch(attributeList);
    }

    @Override
    public List<ProductAttributeDO> getByProductId(Long id, List<Integer> typeList) {

        return new LambdaQueryChainWrapper<>(this.getBaseMapper())
                .eq(ProductAttributeDO::getProductId, id)
                .in(!CollectionUtils.isEmpty(typeList),ProductAttributeDO::getBusinessType, typeList)
                .eq(ProductAttributeDO::getIsDelete, CommonConstants.IS_DELETE_N)
                .list();
    }

    @Override
    public List<AttributeByProductIdDTO> getAttributeByProductId(Long id) {

        return this.getBaseMapper().getAttributeByProductId(id);
    }

    /**
     * 通过code和商品id获取属性map
     *
     * @param showAttributeList 显示属性列表
     * @param productList       产品列表
     * @return 商品id, 属性map
     * @author jp
     * @date 2023/12/26
     */
    @Override
    public Map<Long, Map<String, ProductAttributeListVO>> getAllAttributeByCode(List<String> showAttributeList, List<Long> productList) {
        Map<Long, List<ProductAttributeListVO>> result = getProductAttributeByCode(showAttributeList, productList);
        Map<Long, Map<String, ProductAttributeListVO>> resultMap = new HashMap<>();
        for (Map.Entry entry : result.entrySet()) {
            resultMap.put((Long) entry.getKey(),
                    ((List<ProductAttributeListVO>) entry.getValue()).stream().collect(Collectors.toMap(ProductAttributeListVO::getCode,
                            i -> i, (k1, k2) -> k1)));
        }
        return resultMap;
    }

    /**
     * 通过代码获取所有sku属性
     *
     * @param showAttributeList 显示属性列表
     * @param skuList           SKU列表
     * @return @return {@link Map }<{@link Long }, {@link Map }<{@link String }, {@link ProductAttributeListVO }>>
     * @author jp
     * @date 2024/01/23 17:34
     */
    @Override
    public Map<Long, Map<String, ProductAttributeListVO>> getAllSkuAttributeByCode(List<String> showAttributeList, List<Long> skuList) {
        Map<Long, List<ProductAttributeListVO>> result = getSkuAttributeByCode(showAttributeList, skuList);
        Map<Long, Map<String, ProductAttributeListVO>> resultMap = new HashMap<>();
        for (Map.Entry entry : result.entrySet()) {
            resultMap.put((Long) entry.getKey(),
                    ((List<ProductAttributeListVO>) entry.getValue()).stream().collect(Collectors.toMap(ProductAttributeListVO::getCode,
                            i -> i, (k1, k2) -> k1)));
        }
        return resultMap;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteSkuAttribute(Long productId, List<Long> noDeleteSkuIdList) {

        ArrayList<Long> noDeleteIdList = new ArrayList<>();
        noDeleteIdList.addAll(noDeleteIdList);
        if (!CollectionUtils.isEmpty(noDeleteSkuIdList)) {
            List<ProductSkuExtrasBaseDO> extrasBaseDOList = new LambdaQueryChainWrapper<>(productSkuExtrasBaseMapper)
                    .eq(ProductSkuExtrasBaseDO::getProductId, productId)
                    .in(ProductSkuExtrasBaseDO::getProductSkuId, noDeleteSkuIdList)
                    .list();
            if (!CollectionUtils.isEmpty(extrasBaseDOList)) {
                extrasBaseDOList.forEach(x -> noDeleteIdList.add(x.getId()));
            }
            List<ProductSkuSupplierBaseDO> supplierBaseDOList = new LambdaQueryChainWrapper<>(productSkuSupplierBaseMapper)
                    .eq(ProductSkuSupplierBaseDO::getProductId, productId)
                    .in(ProductSkuSupplierBaseDO::getProductSkuId, noDeleteSkuIdList)
                    .list();
            if (!CollectionUtils.isEmpty(supplierBaseDOList)) {
                supplierBaseDOList.forEach(x -> noDeleteIdList.add(x.getId()));
            }
        }
        new LambdaUpdateChainWrapper<>(this.getBaseMapper())
                .eq(ProductAttributeDO::getProductId, productId)
                .in(ProductAttributeDO::getBusinessType, Arrays.asList(1, 2, 3))
                .notIn(!CollectionUtils.isEmpty(noDeleteIdList), ProductAttributeDO::getBusinessId, noDeleteIdList)
                .remove();

    }

    @Override
    public List<ProductAttributeDO> getProductInfo(List<Long> productIdList) {
        return null;
    }
}
